package uk.co.q3c.deplan.server.unit.domain.task;

import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;

import org.testng.Assert;
import org.testng.annotations.Test;

import uk.co.q3c.deplan.client.domain.dag.ChangeInvalidException;
import uk.co.q3c.deplan.client.domain.dag.CycleDetectedException;
import uk.co.q3c.deplan.client.domain.resource.PersistenceReferenceException;
import uk.co.q3c.deplan.client.domain.task.BaseTask;

@Test
public class SummaryTask_UT extends DomainBase_UT {
	SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yy HH:mm:ss");
	SimpleDateFormat sdf2 = new SimpleDateFormat("dd MMM yy");

	@Override
	protected void beforeMethod() throws Exception {
		super.beforeMethod();
		connection.openSession();
	}

	@Override
	protected void afterMethod() throws Exception {
		connection.closeSession();
		super.afterMethod();
	}

	public void startFinish() throws CycleDetectedException, ChangeInvalidException, PersistenceReferenceException {
		BaseTask st = createStandardTask(1, false);
		BaseTask sum = createStandardTask(2);
		st.setParentTask(sum);
		st.setName("st");
		sum.setName("sum");
		connection.taskService()
				.pushDown(sum);
		connection.taskService()
				.rollup(sum);
		st.save();
		sum.save();
		Assert.assertEquals(st.startTime(), 0);
		Assert.assertEquals(sum.startTime(), 0);
		Assert.assertEquals(st.finishTime(), 0);
		Assert.assertEquals(sum.finishTime(), 0);
		GregorianCalendar cal = new GregorianCalendar();
		cal.set(2008, 03, 02, 11, 0, 0);
		st.setStartRemaining(cal.getTime());
		connection.taskService()
				.rollup(sum);
		st.save();
		// This assumes no actual start
		Assert.assertEquals(st.start(), cal.getTime());
		Assert.assertEquals(sum.start(), cal.getTime());
		cal.set(2008, 03, 03, 11, 0, 0);
		st.setPlannedFinish(cal.getTime());
		connection.taskService()
				.rollup(sum);
		st.save();
		Assert.assertEquals(st.finish(), cal.getTime());
		Assert.assertEquals(sum.finish(), cal.getTime());

		// Now set actualStart and see that it takes precedence
		GregorianCalendar actualCal = new GregorianCalendar();
		actualCal.set(2008, 02, 02, 0, 0, 0);
		st.setActualStart(actualCal.getTime());
		st.setStartRemaining(cal.getTime());
		Assert.assertEquals(st.startTime(), actualCal.getTimeInMillis());
		connection.taskService()
				.rollup(sum);
		st.save();
		// confirm start() is now actualStart() for task and summary
		// and startRemaining is unaffected
		Assert.assertEquals(sdf.format(st.start()), sdf.format(actualCal.getTime()));
		Assert.assertEquals(sum.start()
				.getTime(), actualCal.getTimeInMillis());
		Assert.assertEquals(st.getStartRemaining()
				.getTime(), cal.getTimeInMillis());
		// revert actualStart to null to avoid confusing the next test
		st.setActualStart(null);
		st.save();

		// add a second sub task with earlier start and earlier plannedFinish
		BaseTask st2 = createStandardTask(3, false);
		st2.setName("st2");
		st2.setParentTask(sum);
		// earlier start
		GregorianCalendar cal2 = new GregorianCalendar();
		cal2.set(2008, 03, 01, 11, 0, 0);
		st2.setStartRemaining(cal2.getTime());
		// later plannedFinish
		GregorianCalendar cal3 = new GregorianCalendar();
		cal3.set(2008, 3, 8, 11, 0, 0);
		st2.setPlannedFinish(cal3.getTime());
		connection.taskService()
				.rollup(sum);
		st2.save();
		System.out.println("st start=" + st.start());
		System.out.println("st2.start=" + st2.start());
		System.out.println("sum start=" + sum.start());

		// summary starts at earliest start
		Assert.assertEquals(sum.start(), st2.start());
		// summary finishes at latest plannedFinish
		Assert.assertEquals(sum.finish(), st2.finish());

	}

}
